package com.dream.net.websocket;

import com.dream.common.utils.SessionUtils;
import com.dream.common.utils.ThreadContextUtil;
import com.dream.common.utils.ThreadPoolService;
import com.dream.entity.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BaseWebSocket extends TextWebSocketHandler {

    private final static Logger logger = LoggerFactory.getLogger(BaseWebSocket.class);

    /**
     * key:userName,value：<sessionId,channel>一个用户会有多地登陆，
     * 都需要进行推送
     */
    private static final Map<String,Map<String,WebSocketSession>> WEB_USERS = new ConcurrentHashMap<>(500);

    /**
     * 连接成功时候，会触发Web端onopen方法
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//        String userName = ThreadContextUtil.get("userName").toString();
//        logger.info("建立WebSocket连接成功! sessionId: {} userName:{}",session.getId(),userName);
//        UserInfo userInfo = new UserInfo();
//        userInfo.user = userName;
//        session.getAttributes().put(SessionUtils.USER_INFO,userInfo);
//
//        Map<String,WebSocketSession> channels = WEB_USERS.get(userName);
//        if(CollectionUtils.isEmpty(channels)){
//            channels = new HashMap<>(25);
//            channels.put(session.getId(),session);
//            WEB_USERS.put(userName,channels);
//            return;
//        }
//        channels.put(session.getId(),session);
    }


    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        session.sendMessage(message);
    }


    /**
     * 给某个用户发送消息
     */
    public void sendMessageToUser(String userName, String message) {
        Map<String,WebSocketSession> userChannels = WEB_USERS.get(userName);
        if(!CollectionUtils.isEmpty(userChannels)){
            ThreadPoolService.execute(()-> userChannels.forEach((sessionId, channel)->{
                if (channel.isOpen()) {
                    try {
                        channel.sendMessage(new TextMessage(message));
                    } catch (IOException e) {
                        logger.error("sendMessage error user: {} trace msg : {}",userName,e.toString());
                    }
                    logger.info("向前端用户 userName : {} sessionId: {} message:{}",userName,sessionId,message);
                }
            }));
        }
    }



    /**
     * 给所有在线用户发送消息
     */
    public void sendMessageToUsers(TextMessage message) {
        WEB_USERS.forEach((userName, channels) ->
                channels.forEach((sessionId,channel) -> {
                    try {
                        if (channel.isOpen()) {
                            channel.sendMessage(message);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                })
        );
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        String userName = SessionUtils.getUserInfoFromWebSocket(session).user;
        Map<String,WebSocketSession> userChannels = WEB_USERS.get(userName);
        if(!CollectionUtils.isEmpty(userChannels)){
            userChannels.remove(session.getId());
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
//        String userName = SessionUtils.getUserInfoFromWebSocket(session).user;
//        Map<String,WebSocketSession> userChannels = WEB_USERS.get(userName);
//        if(!CollectionUtils.isEmpty(userChannels)){
//            userChannels.remove(session.getId());
//        }
    }

    /**
     * 是否支持消息拆分发送：如果接收的数据量比较大，最好打开(true), 否则可能会导致接收失败。
     * 如果出现WebSocket连接接收一次数据后就自动断开，应检查是否是这里的问题。
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
        super.handlePongMessage(session, message);
    }
}
